package com.cskaoyan.order.biz.handler;

import com.alibaba.fastjson.JSON;
import com.cskaoyan.mall.commons.constant.SysRetCodeConstants;
import com.cskaoyan.mall.commons.exception.BaseBusinessException;
import com.cskaoyan.mall.commons.exception.BizException;
import com.cskaoyan.order.biz.context.AbsTransHandlerContext;
import com.cskaoyan.order.biz.context.CreateOrderContext;
import com.cskaoyan.order.biz.context.TransHandlerContext;
import com.cskaoyan.order.dal.entitys.Stock;
import com.cskaoyan.order.dal.persistence.StockMapper;
import com.cskaoyan.order.dto.CartProductDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description: 扣减库存处理器
 **/
@Component
@Slf4j
public class SubStockHandler extends AbstractTransHandler {

    @Autowired
    StockMapper stockMapper;

    @Override
    public boolean isAsync() {
        return false;
    }

    /**
     * 根据购物车中商品列表信息，对指定商品的库存数进行修改更新
     *
     * @param context 封装有请求信息的对象
     * @return boolean
     * @author Chen_Feng
     * @since 2022/07/09 9:52
     */
    @Override
    // @Transactional
    public boolean handle(TransHandlerContext context) {

        CreateOrderContext createOrderContext = (CreateOrderContext) context;

        // 获得购物车中商品列表
        List<CartProductDto> cartProductDtoList = createOrderContext.getCartProductDtoList();

        // 将商品列表中的商品id形成一个list
        ArrayList<Long> itemIdList = new ArrayList<>();
        for (CartProductDto cartProductDto : cartProductDtoList) {
            itemIdList.add(cartProductDto.getProductId());
        }

        // 查询购物车中所有商品库存的信息
        Example example = new Example(Stock.class);
        example.createCriteria().andIn("itemId", itemIdList);
        List<Stock> stockList = null;
        try {
            stockList = stockMapper.selectByExample(example);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(SysRetCodeConstants.DB_EXCEPTION.getCode(), SysRetCodeConstants.DB_EXCEPTION.getMessage());
        }

        // 修改对应商品库存
        doUpdateStockCount(cartProductDtoList, stockList);

        // 将itemIdList赋值给context的buyProductIds
        createOrderContext.setBuyProductIds(itemIdList);

        return true;
    }

    /**
     * 修改库存商品表中的库存数
     *
     * @param cartProductDtoList
     * @param stockList
     * @return void
     * @author Chen_Feng
     * @since 2022/07/11 0:02
     */
    private void doUpdateStockCount(List<CartProductDto> cartProductDtoList, List<Stock> stockList) {
        Stock tempStock = new Stock();
        for (CartProductDto cartProductDto : cartProductDtoList) {
            for (Stock stock : stockList) {

                // 当两个对象的id一致时才执行操作，否则跳过
                if (!Objects.equals(stock.getItemId(), cartProductDto.getProductId())) {
                    continue;
                }

                Long productNum = cartProductDto.getProductNum(); // 下单时商品购买数
                Long beforeStockCount = stock.getStockCount(); // 商品下单前的可用库存数

                // 如果库存不够，则抛出异常
                if (beforeStockCount < productNum) {
                    throw new BizException(SysRetCodeConstants.REQUEST_DATA_ERROR.getCode(), "商品购买数大于库存数");
                }

                Integer beforeLockCount = stock.getLockCount(); // 商品下单前的库存锁定数
                Long afterStockCount = beforeStockCount - productNum; // 商品下单后可用库存数
                Integer afterLockCount = Math.toIntExact(beforeLockCount + productNum); // 商品下单后锁定库存数

                // 封装一个Do对象
                tempStock.setItemId(stock.getItemId());
                tempStock.setStockCount(afterStockCount);
                tempStock.setLockCount(afterLockCount);

                // 更新数据库库存表，进行下一轮外层循环
                try {
                    stockMapper.updateByPrimaryKeySelective(tempStock);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new BizException(SysRetCodeConstants.DB_EXCEPTION.getCode(), SysRetCodeConstants.DB_EXCEPTION.getMessage());
                }
                break;
            }
        }
    }
}